/**
 @file sys_at_peri.c

 @date 2021-12-07

 @version v1.0

 The file define APIs of peri of sys layer
*/
/****************************************************************************
 *
 * Header Files
 *
 ****************************************************************************/
#include "sal.h"
#include "ctc_error.h"
#include "ctc_macro.h"
#include "sys_at_peri.h"
#include "sys_usw_peri.h"
#include "sys_usw_interrupt.h"
#include "sys_usw_chip_global.h"
#include "sys_usw_port_api.h"
#include "sys_usw_eunit.h"
#include "drv_api.h"

/****************************************************************************
 *
* Defines and Macros
*
*****************************************************************************/

/* 1 top sensor + 5 other sensors per core */
#define SYS_AT_PERI_SENSOR_NUM_PER_CORE (6)
#define SYS_AT_PERI_NUM_PER_TWO_PP 130
#define SYS_AT_PERI_MAC_NUM_PER_PP 64
#define SYS_AT_PERI_MAC_NUM_PER_DP 32

/* sensor 0-5 is form core 0, sensor 6-11 is from core1 */
#define SYS_PERI_SENSOR_MAP_LCHIP(lchip, sensor_id) \
    do{\
        (lchip) = SYS_PP_BASE(lchip) + (((sensor_id) >= SYS_AT_PERI_SENSOR_NUM_PER_CORE) ? (SYS_PP_NUM(lchip) / 2) : 0);\
    }while(0);

#define SYS_AT_SENSOR_MIN_THRD 90
#define SYS_AT_SENSOR_MAX_THRD 125
#define SYS_AT_SENSOR_MIN_INTERVAL 10
/* IntrIntCtl bit18~bit29 is triggered by ecpu for sensor monitor, refer to sys_at_eunit_intr_t */
#define SYS_AT_SENSOR_INTR_BASE 18

/* default LED reference Clock, 1000 MHz */
#define SYS_AT_PERI_LED_CLOCK_REF (1000)

/* default MDIO reference Clock, 50 MHz */
#define SYS_AT_PERI_MDIO_CLOCK_REF (50)

#define SYS_AT_PERI_MAX_DIVIDED_NUM (32)

enum sys_at_peri_sensor_id_e
{
    SYS_AT_PERI_SENSOR_ID_0,  /* sensor0 in core 0, near BSR */
    SYS_AT_PERI_SENSOR_ID_1,  /* sensor1 in core 0, near pp0 */
    SYS_AT_PERI_SENSOR_ID_2,  /* sensor2 in core 0, near pp1 */
    SYS_AT_PERI_SENSOR_ID_3,  /* sensor3 in core 0, near pp2  */
    SYS_AT_PERI_SENSOR_ID_4,  /* sensor4 in core 0, near pp3 */
    SYS_AT_PERI_SENSOR_ID_5,  /* sensor5 in core 0, near serdes */
    SYS_AT_PERI_SENSOR_ID_6,  /* sensor6 in core 1, near BSR */
    SYS_AT_PERI_SENSOR_ID_7,  /* sensor7 in core 1, near pp0 */
    SYS_AT_PERI_SENSOR_ID_8,  /* sensor8 in core 1, near pp1 */
    SYS_AT_PERI_SENSOR_ID_9,  /* sensor9 in core 1, near pp2 */
    SYS_AT_PERI_SENSOR_ID_10, /* sensor10 in core 1, near pp3 */
    SYS_AT_PERI_SENSOR_ID_11, /* sensor11 in core 1, near serdes */

    SYS_AT_PERI_SENSOR_ID_MAX
};
typedef enum sys_at_peri_sensor_id_e sys_at_peri_sensor_id_t;

/****************************************************************************
 *
 * Global and static
 *
 *****************************************************************************/

/****************************************************************************
 *
 * Function
 *
 *****************************************************************************/

extern int32
sys_tsingma_peri_set_phy_scan_para(uint8 lchip, ctc_chip_phy_scan_ctrl_t* p_scan_para);
extern int32
sys_tsingma_peri_set_phy_scan_cfg(uint8 lchip);

#define __MDIO_INTERFACE__

int32
sys_at_peri_set_mdio_clock(uint8 lchip, ctc_chip_mdio_type_t type, uint16 freq)
{
    uint32 cmd = 0;
    uint32 cfg_tbl = 0, cfg_tbl_idx = 0;
    uint8 tmp_type = 0;
    ds_t ds;
    uint8 control_id = 0;
    uint32 div = 0, value = 0, core_freq = SYS_AT_PERI_MDIO_CLOCK_REF;
    uint32 control_tbl[4] = {MdioAPart0CwgDskCfg_t, MdioAPart1CwgDskCfg_t, MdioBPart0CwgDskCfg_t, MdioBPart1CwgDskCfg_t};
    uint32 field_id_div[4] = {MdioAPart0CwgDskCfg_cfgClkMdioAPart0Divide_f, MdioAPart1CwgDskCfg_cfgClkMdioAPart1Divide_f,\
                              MdioBPart0CwgDskCfg_cfgClkMdioBPart0Divide_f, MdioBPart1CwgDskCfg_cfgClkMdioBPart1Divide_f};
    uint32 field_id_width[4] = {MdioAPart0CwgDskCfg_cfgClkMdioAPart0Width_f, MdioAPart1CwgDskCfg_cfgClkMdioAPart1Width_f,\
                              MdioBPart0CwgDskCfg_cfgClkMdioBPart0Width_f, MdioBPart1CwgDskCfg_cfgClkMdioBPart1Width_f};
    uint32 field_id_edge[4] = {MdioAPart0CwgDskCfg_cfgClkMdioAPart0Edge_f, MdioAPart1CwgDskCfg_cfgClkMdioAPart1Edge_f,\
                              MdioBPart0CwgDskCfg_cfgClkMdioBPart0Edge_f, MdioBPart1CwgDskCfg_cfgClkMdioBPart1Edge_f};
    uint32 field_id_localgo[4] = {MdioAPart0CwgDskCfg_cfgClkMdioAPart0Localgo_f, MdioAPart1CwgDskCfg_cfgClkMdioAPart1Localgo_f,\
                              MdioBPart0CwgDskCfg_cfgClkMdioBPart0Localgo_f, MdioBPart1CwgDskCfg_cfgClkMdioBPart1Localgo_f};
    uint32 field_id_reset[4] = {MdioAPart0CwgDskCfg_cfgClkMdioAPart0Reset_f, MdioAPart1CwgDskCfg_cfgClkMdioAPart1Reset_f,\
                                MdioBPart0CwgDskCfg_cfgClkMdioBPart0Reset_f, MdioBPart1CwgDskCfg_cfgClkMdioBPart1Reset_f};

    SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_MIN_VALUE_CHECK(freq, 1);
    CTC_MAX_VALUE_CHECK(freq, 60000);

    div = ((core_freq*1000) % freq == 0) ? (core_freq*1000)/freq : ((core_freq*1000)/freq) + 1;
    if(SYS_AT_PERI_MAX_DIVIDED_NUM < div)
    {
        SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "div is out of bound, div:%u\tcfg frequency:%u\tclockMdioHi frequency:%u\n", div, freq, core_freq);
        return CTC_E_INVALID_PARAM;
    }
    if(div < 1)
    {
        SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "clockMdioHi frequency:%uKHz, MDIO frequency you config:%uKHz\n", core_freq*1000, freq);
        return CTC_E_INVALID_PARAM;
    }

    for(control_id = 0; control_id < SYS_PERI_MDIO_CTRL_NUM_PER_CORE; control_id++)
    {
        cfg_tbl = ((SYS_MDIO_CONTROL_ID0 == control_id) || \
                   (SYS_MDIO_CONTROL_ID1 == control_id)) ? MdioCfg0_t:MdioCfg1_t;
        cfg_tbl_idx = control_id % 2;

        cmd = DRV_IOR(cfg_tbl, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, cfg_tbl_idx, cmd, &ds));
        tmp_type = GetMdioCfg0(V, mdioIsXgModeLane0_f, &ds);
        if(type != tmp_type)
        {
            continue;
        }

        /* config divide */
        value = div - 1;
        cmd = DRV_IOW(control_tbl[control_id], field_id_div[control_id]);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

        /* config width */
        value = (div - 1) / 2;
        cmd = DRV_IOW(control_tbl[control_id], field_id_width[control_id]);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

        /* second half clock transition happen at rising edge(1) or falling edge(0) */
        value = ((div & 0x1) == 0);
        cmd = DRV_IOW(control_tbl[control_id], field_id_edge[control_id]);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

        /* config output clock enable */
        value = 1;
        cmd = DRV_IOW(control_tbl[control_id], field_id_localgo[control_id]);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

        /* reset MDIO divider */
        value = 1;
        cmd = DRV_IOW(control_tbl[control_id], field_id_reset[control_id]);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

        /* release MDIO divider reset */
        value = 0;
        cmd = DRV_IOW(control_tbl[control_id], field_id_reset[control_id]);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    }

    return CTC_E_NONE;
}

int32
sys_at_peri_get_mdio_clock(uint8 lchip, ctc_chip_mdio_type_t type, uint16* freq)
{
    uint32 cmd = 0;
    ds_t ds;
    uint32 core_freq = SYS_AT_PERI_MDIO_CLOCK_REF;
    uint8 control_id = 0;
    uint32 cfg_tbl = 0, cfg_tbl_idx = 0, value = 0;
    uint32 tmp_type = 0;
    uint32 control_tbl[4] = {MdioAPart0CwgDskCfg_t, MdioAPart1CwgDskCfg_t, MdioBPart0CwgDskCfg_t, MdioBPart1CwgDskCfg_t};
    uint32 field_id_div[4] = {MdioAPart0CwgDskCfg_cfgClkMdioAPart0Divide_f, MdioAPart1CwgDskCfg_cfgClkMdioAPart1Divide_f,\
                              MdioBPart0CwgDskCfg_cfgClkMdioBPart0Divide_f, MdioBPart1CwgDskCfg_cfgClkMdioBPart1Divide_f};
    uint32 field_id_localgo[4] = {MdioAPart0CwgDskCfg_cfgClkMdioAPart0Localgo_f, MdioAPart1CwgDskCfg_cfgClkMdioAPart1Localgo_f,\
                              MdioBPart0CwgDskCfg_cfgClkMdioBPart0Localgo_f, MdioBPart1CwgDskCfg_cfgClkMdioBPart1Localgo_f};

    SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    for (control_id = 0; control_id < SYS_PERI_MDIO_CTRL_NUM_PER_CORE; control_id++)
    {
        cfg_tbl = ((SYS_MDIO_CONTROL_ID0 == control_id) || \
        (SYS_MDIO_CONTROL_ID1 == control_id)) ? MdioCfg0_t : MdioCfg1_t;
        cfg_tbl_idx = control_id % 2;

        cmd = DRV_IOR(cfg_tbl, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, cfg_tbl_idx, DRV_CMD_PP_EN(cmd), &ds));
        tmp_type = GetMdioCfg0(V, mdioIsXgModeLane0_f, &ds);
        if (type == tmp_type)
        {
            cmd = DRV_IOR(control_tbl[control_id], field_id_localgo[control_id]);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &value));
            if (value)
            {
                cmd = DRV_IOR(control_tbl[control_id], field_id_div[control_id]);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &value));
                *freq = core_freq*1000 / (value + 1);
            }
            else
            {
                SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "MDIO clock output not enable\n");
                return CTC_E_HW_FAIL;
            }
            break;
        }
    }

    return CTC_E_NONE;
}

#define __LED_INTERFACE___

STATIC int32
_sys_at_peri_get_mac_led_div(uint32 div_in, uint32* div1_out, uint32 *div2_out)
{
    uint8 tmp_div = 32;

    if (div_in <= SYS_AT_PERI_MAX_DIVIDED_NUM)
    {
        *div1_out = div_in;
        *div2_out = 1;
    }
    else
    {
        while((tmp_div != 0) && (div_in % tmp_div != 0))
        {
            tmp_div--;
        }

        if (tmp_div <= 1)
        {
            *div1_out = 32;
            *div2_out = div_in / 32 + 1;
        }
        else
        {
            *div1_out = tmp_div;
            *div2_out = div_in / tmp_div;
        }
    }

    return CTC_E_NONE;
}

int32
sys_at_peri_set_mac_led_clock(uint8 lchip, uint16 freq)
{
    uint32 cmd = 0;
    uint32 div = 0, div1 = 0, div2 = 0, div_reset = 0;
    uint32 core_freq = SYS_AT_PERI_LED_CLOCK_REF;
    ds_t ds;

    SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_MIN_VALUE_CHECK(freq, 1);

    div = (core_freq*1000/freq);
    /* LED module includes 2 dividers, the first is HiCwgDsk, the second is CwgDsk,
     * each div is 32 MAX, so the max divider is 32*32 = 1024 */
    if(SYS_AT_PERI_MAX_DIVIDED_NUM*SYS_AT_PERI_MAX_DIVIDED_NUM < div)
    {
        SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%s(), freq %u out of bound\n", __FUNCTION__, freq);
        return CTC_E_INVALID_PARAM;
    }
    if(div < 1)
    {
        SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "clockTsRef frequency:%u MHz is less than you config\n", core_freq);
        return CTC_E_INVALID_PARAM;
    }

    div = (core_freq*1000 % freq != 0) ? (div + 1):div;
    _sys_at_peri_get_mac_led_div(div, &div1, &div2);

    /* 1. config divider 1 */
    cmd = DRV_IOR(LedHiCwgDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetLedHiCwgDskCfg(V, cfgClkLedHiDivide_f, &ds, div1 - 1);
    SetLedHiCwgDskCfg(V, cfgClkLedHiWidth_f, &ds, (div1 - 1) / 2);
    SetLedHiCwgDskCfg(V, cfgClkLedHiLocalgo_f, &ds, 1);
    SetLedHiCwgDskCfg(V, cfgClkLedHiEdge_f, &ds, (div1 & 0x1)?0:1);
    cmd = DRV_IOW(LedHiCwgDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    /* reset divider 1 */
    div_reset = 1;
    cmd = DRV_IOW(LedHiCwgDskCfg_t, LedHiCwgDskCfg_cfgClkLedHiReset_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &div_reset));
    div_reset = 0;
    cmd = DRV_IOW(LedHiCwgDskCfg_t, LedHiCwgDskCfg_cfgClkLedHiReset_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &div_reset));

    /* 2. config divider 2, config a fixed value 2 */
    cmd = DRV_IOR(LedCwgDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetLedCwgDskCfg(V, cfgClkLedDivide_f, &ds, div2 - 1);
    SetLedCwgDskCfg(V, cfgClkLedWidth_f, &ds, (div2 - 1) / 2);
    SetLedCwgDskCfg(V, cfgClkLedLocalgo_f, &ds, 1);
    SetLedCwgDskCfg(V, cfgClkLedEdge_f, &ds, (div2 & 0x1)?0:1);
    cmd = DRV_IOW(LedCwgDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    /* reset divider 2 */
    div_reset = 1;
    cmd = DRV_IOW(LedCwgDskCfg_t, LedCwgDskCfg_cfgClkLedReset_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &div_reset));
    div_reset = 0;
    cmd = DRV_IOW(LedCwgDskCfg_t, LedCwgDskCfg_cfgClkLedReset_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &div_reset));

    return CTC_E_NONE;
}

int32
sys_at_peri_get_mac_led_clock(uint8 lchip, uint16* freq)
{
    uint32 cmd = 0;
    uint32 div1 = 0, div2 = 0;
    uint32 core_freq = SYS_AT_PERI_LED_CLOCK_REF;
    uint8 clk_output_en = 0;
    ds_t ds;

    SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    cmd = DRV_IOR(LedHiCwgDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    clk_output_en = GetLedHiCwgDskCfg(V, cfgClkLedHiLocalgo_f, &ds);
    if (clk_output_en)
    {
        div1 = GetLedHiCwgDskCfg(V, cfgClkLedHiDivide_f, &ds);
    }
    else
    {
        SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "LED HiCwgDsk clock output not enable\n");
        return CTC_E_HW_FAIL;
    }

    cmd = DRV_IOR(LedCwgDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    clk_output_en = GetLedCwgDskCfg(V, cfgClkLedLocalgo_f, &ds);
    if (clk_output_en)
    {
        div2 = GetLedCwgDskCfg(V, cfgClkLedDivide_f, &ds);
    }
    else
    {
        SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "LED CwgDsk clock output not enable\n");
        return CTC_E_HW_FAIL;
    }

    *freq = (core_freq*1000) / ((div1+1)*(div2+1));

    return CTC_E_NONE;
}

#define __SENSOR_INTERFACE___

STATIC int32
_sys_at_peri_get_sensor_tbl_id(uint8 lchip, uint8 sensor_id, uint32* cfg_tbl_id, uint32* data_tbl_id, uint32* width_cfg_tbl_id, uint32* tbl_idx)
{
    if(SYS_AT_PERI_SENSOR_ID_5 == sensor_id || SYS_AT_PERI_SENSOR_ID_11 == sensor_id)
    {
        *cfg_tbl_id = TvsenCfgTop_t;
        *data_tbl_id = TvsenDataRdyTop_t;
        *width_cfg_tbl_id = TvsenStartPulseWidthCfgTop_t;
        *tbl_idx = 0;
    }
    else
    {
        *cfg_tbl_id = TvsenCfg_t;
        *data_tbl_id = TvsenDataRdy_t;
        *width_cfg_tbl_id = TvsenStartPulseWidthCfg_t;
        *tbl_idx = (sensor_id >= SYS_AT_PERI_SENSOR_ID_6)?(sensor_id - SYS_AT_PERI_SENSOR_ID_6):(sensor_id - SYS_AT_PERI_SENSOR_ID_0);
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_at_peri_sensor_result_proc(uint8 lchip, uint32* measure_result, uint8 type)
{
    int32 raw_data = 0;
    int32 real_data = 0;

    /* measure_result is a 12-bit signed integer, bit11 is sign bit */
    if ((*measure_result) & 0x800)
    {
        raw_data = 4096 - *measure_result;
    }
    else
    {
        raw_data = (*measure_result) & 0xfff;
    }

    if(CTC_CHIP_SENSOR_TEMP == type)
    {
        if ((*measure_result) & 0x800)
        {
            real_data = (1180000 - raw_data * 950)/10000;
            *measure_result = real_data < 0 ? ((0 - real_data) | (1 << 31)) : (uint32)real_data;
        }
        else
        {
            *measure_result = (1180000 + raw_data * 950)/10000;
        }
    }
    else
    {
        if ((*measure_result) & 0x800)
        {
            *measure_result = (raw_data * (5868)/10000);
        }
        else
        {
            real_data = -(raw_data * (5868)/10000);
            *measure_result = real_data < 0 ? ((0 - real_data) | (1 << 31)) : (uint32)real_data;
        }
    }

    return CTC_E_NONE;
}

int32
sys_at_peri_get_chip_sensor(uint8 lchip, void* sensor)
{
    ctc_chip_sensor_t* p_sensor = (ctc_chip_sensor_t*)sensor;
    uint32 cmd = 0;
    uint32 cfg_tbl_id, data_tbl_id, width_cfg_tbl_id, tbl_idx;
    uint32 timeout = 0;
    uint32 measure_result = 0;
    int32 ret = CTC_E_NONE;
    uint8 data_rdy = 0;
    uint8 sensor_id = 0;
    uint8 sensor_cnt = 0;
    TvsenCfg_m senCfg;
    TvsenDataRdy_m senData;
    TvsenStartPulseWidthCfg_m widthCfg;
    uint8 sensor_num;

#if (defined E_UNIT) && (FEATURE_MODE == 0)
    uint8 eunit_id = 0;
    uint8 lock_id = 0;
    SYS_EUNIT_GET_HW_LOCK(lchip, SYS_EUNIT_CFG_SENSOR_MONITOR, &eunit_id, &lock_id);
    SYS_EUNIT_HW_LOCK(lchip, eunit_id, lock_id);
#endif

    /* 12 sensor for dul-core, 6 sensors for single core */
    sensor_num = (drv_get_chip_sub_type(lchip) >= DRV_CHIP_SUB_TYPE_3) ? SYS_AT_PERI_SENSOR_ID_MAX : (SYS_AT_PERI_SENSOR_ID_MAX/2);
    for (sensor_id = 0; sensor_id < sensor_num; sensor_id++)
    {
        _sys_at_peri_get_sensor_tbl_id(lchip, sensor_id, &cfg_tbl_id, &data_tbl_id, &width_cfg_tbl_id, &tbl_idx);
        SYS_PERI_SENSOR_MAP_LCHIP(lchip, sensor_id);

        /* disable and reset ADC first */
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcStart_f, &senCfg, 0);
        SetTvsenCfg(V, cfgTsenAdcEn_f, &senCfg, 0);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        sal_task_sleep(1);

        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcReset_f, &senCfg, 1);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        sal_task_sleep(1);
        SetTvsenCfg(V, cfgTsenAdcReset_f, &senCfg, 0);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 1. cfg measure mode, default use single mode */
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcSingleShotEn_f, &senCfg, 1);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 2. cfg measure type, temperature or voltage*/
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcMode_f, &senCfg, (CTC_CHIP_SENSOR_TEMP == p_sensor->type)?0:1);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 3. cfg ADC reset before measurement*/
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcReset_f, &senCfg, 0);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 4. enable ADC*/
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcEn_f, &senCfg, 1);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 5. wait 127920ns */
        sal_task_sleep(1);

        /* 6. cfg measure period */
        cmd = DRV_IOR(width_cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &widthCfg), ret, roll_back);
        SetTvsenStartPulseWidthCfg(V, cfgTsenAdcStartFirstPulseWidth_f, &widthCfg, 1601184);
        cmd = DRV_IOW(width_cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &widthCfg), ret, roll_back);

        /* 7. start measurement */
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcStart_f, &senCfg, 1);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 8. wait 16011840ns */
        sal_task_sleep(17);

        /* 9. end measurement */
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcStart_f, &senCfg, 0);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 10. wait 1603680ns */
        sal_task_sleep(2);

        /* 11. read measure result */
        cmd = DRV_IOR(data_tbl_id, DRV_ENTRY_FLAG);
        timeout = 1000;
        do{
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senData), ret, roll_back);
            data_rdy = GetTvsenDataRdy(V, tsenAdcDataReady_f, &senData);
            if (data_rdy)
            {
                measure_result = GetTvsenDataRdy(V, tsenAdcData_f, &senData);
                _sys_at_peri_sensor_result_proc(lchip, &measure_result, p_sensor->type);
                p_sensor->value[sensor_cnt++] = measure_result;
                break;
            }
            sal_task_sleep(1);
        }while(timeout--);
    }
    p_sensor->count = sensor_cnt;

roll_back:
#if (defined E_UNIT) && (FEATURE_MODE == 0)
    SYS_EUNIT_HW_UNLOCK(lchip, eunit_id, lock_id);
#endif
    return ret;
}

int32
sys_at_peri_get_chip_sensor2(uint8 lchip, void* sensor)
{
    ctc_chip_sensor_t* p_sensor = (ctc_chip_sensor_t*)sensor;
    uint32 cmd = 0;
    uint32 cfg_tbl_id, data_tbl_id, width_cfg_tbl_id, tbl_idx;
    uint32 timeout = 0;
    uint32 measure_result = 0;
    int32 ret = CTC_E_NONE;
    uint8 data_rdy = 0;
    uint8 sensor_id = 0;
    uint8 sensor_cnt = 0;
    TvsenCfg_m senCfg;
    TvsenDataRdy_m senData;
    uint8 sensor_sum;

#if (defined E_UNIT) && (FEATURE_MODE == 0)
    uint8 eunit_id = 0;
    uint8 lock_id = 0;
    SYS_EUNIT_GET_HW_LOCK(lchip, SYS_EUNIT_CFG_SENSOR_MONITOR, &eunit_id, &lock_id);
    SYS_EUNIT_HW_LOCK(lchip, eunit_id, lock_id);
#endif

    SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Using continus mode\n");

    /* 12 sensor for dul-core, 6 sensors for single core */
    sensor_sum = (drv_get_chip_sub_type(lchip) >= DRV_CHIP_SUB_TYPE_3) ? SYS_AT_PERI_SENSOR_ID_MAX : (SYS_AT_PERI_SENSOR_ID_MAX/2);
    for (sensor_id = 0; sensor_id < sensor_sum; sensor_id++)
    {
        _sys_at_peri_get_sensor_tbl_id(lchip, sensor_id, &cfg_tbl_id, &data_tbl_id, &width_cfg_tbl_id, &tbl_idx);
        SYS_PERI_SENSOR_MAP_LCHIP(lchip, sensor_id);

        /* disable and reset ADC first */
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcStart_f, &senCfg, 0);
        SetTvsenCfg(V, cfgTsenAdcEn_f, &senCfg, 0);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        sal_task_sleep(1);

        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcReset_f, &senCfg, 1);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        sal_task_sleep(1);
        SetTvsenCfg(V, cfgTsenAdcReset_f, &senCfg, 0);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 1. cfg measure mode, default use continus mode */
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcSingleShotEn_f, &senCfg, 0);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 2. cfg measure type, temperature or voltage*/
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcMode_f, &senCfg, (CTC_CHIP_SENSOR_TEMP == p_sensor->type)?0:1);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 3. cfg ADC reset before measurement*/
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcReset_f, &senCfg, 0);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 4. enable ADC and start measuring */
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcEn_f, &senCfg, 1);
        SetTvsenCfg(V, cfgTsenAdcStart_f, &senCfg, 1);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 5. wait at least 30510480ns */
        sal_task_sleep(35);

        /* 6. disable ADC and stop measuring */
        cmd = DRV_IOR(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);
        SetTvsenCfg(V, cfgTsenAdcEn_f, &senCfg, 0);
        SetTvsenCfg(V, cfgTsenAdcStart_f, &senCfg, 0);
        cmd = DRV_IOW(cfg_tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senCfg), ret, roll_back);

        /* 7. read measure result */
        cmd = DRV_IOR(data_tbl_id, DRV_ENTRY_FLAG);
        timeout = 1000;
        do{
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, tbl_idx, DRV_CMD_PP_EN(cmd), &senData), ret, roll_back);
            data_rdy = GetTvsenDataRdy(V, tsenAdcDataReady_f, &senData);
            if (data_rdy)
            {
                measure_result = GetTvsenDataRdy(V, tsenAdcData_f, &senData);
                _sys_at_peri_sensor_result_proc(lchip, &measure_result, p_sensor->type);
                p_sensor->value[sensor_cnt++] = measure_result;
                break;
            }
            sal_task_sleep(1);
        }while(timeout--);
    }

    p_sensor->count = sensor_cnt;
    
roll_back:
#if (defined E_UNIT) && (FEATURE_MODE == 0)
    SYS_EUNIT_HW_UNLOCK(lchip, eunit_id, lock_id);
#endif
    return ret;
}


int32
sys_at_peri_set_sensor_monitor(uint8 lchip, void* sen_monitor)
{
#if defined E_UNIT && (FEATURE_MODE == 0)
    ctc_chip_sensor_monitor_t* p_sen_monitor = (ctc_chip_sensor_monitor_t*)sen_monitor;
    sys_eunit_peri_sensor_cfg_t sensor_cfg;

    CTC_VALUE_RANGE_CHECK(p_sen_monitor->on_thrd, SYS_AT_SENSOR_MIN_THRD, SYS_AT_SENSOR_MAX_THRD);
    CTC_VALUE_RANGE_CHECK(p_sen_monitor->off_thrd, SYS_AT_SENSOR_MIN_THRD, SYS_AT_SENSOR_MAX_THRD);
    CTC_MAX_VALUE_CHECK(p_sen_monitor->off_thrd, p_sen_monitor->on_thrd);
    CTC_MIN_VALUE_CHECK(p_sen_monitor->interval,SYS_AT_SENSOR_MIN_INTERVAL);

    sal_memset(&sensor_cfg, 0, sizeof(sys_eunit_peri_sensor_cfg_t));
    sensor_cfg.interval = p_sen_monitor->interval;
    sensor_cfg.on_thrd = p_sen_monitor->on_thrd;
    sensor_cfg.off_thrd = p_sen_monitor->off_thrd;
    sensor_cfg.sensor_bmp = p_sen_monitor->sensor_bmp;
    CTC_ERROR_RETURN(sys_usw_eunit_set_cfg(lchip, SYS_EUNIT_CFG_SENSOR_MONITOR, &sensor_cfg));

    return CTC_E_NONE;
#else
    return CTC_E_NOT_SUPPORT;
#endif
}


int32
sys_at_peri_get_sensor_monitor(uint8 lchip, void* sen_monitor)
{
#if defined E_UNIT && (FEATURE_MODE == 0)
    ctc_chip_sensor_monitor_t* p_sen_monitor = (ctc_chip_sensor_monitor_t*)sen_monitor;
    sys_eunit_peri_sensor_cfg_t sensor_cfg;

    CTC_ERROR_RETURN(sys_usw_eunit_get_cfg(lchip, SYS_EUNIT_CFG_SENSOR_MONITOR, &sensor_cfg));
    p_sen_monitor->interval = sensor_cfg.interval;
    p_sen_monitor->on_thrd = sensor_cfg.on_thrd;
    p_sen_monitor->off_thrd = sensor_cfg.off_thrd;
    p_sen_monitor->sensor_bmp = sensor_cfg.sensor_bmp;
    return CTC_E_NONE;
#else
    return CTC_E_NOT_SUPPORT;
#endif
}

extern int32
sys_at_eunit_get_cfg(uint8 lchip, uint8 cfg_type, void* p_cfg);
extern int32
sys_at_eunit_set_cfg(uint8 lchip, uint8 cfg_type, void* p_cfg);

int32
sys_at_peri_sensor_monitor_isr(uint8 lchip, uint8 isr_type, void* p_data)
{
#if defined E_UNIT && (FEATURE_MODE == 0)
    CTC_INTERRUPT_EVENT_FUNC sen_mon_cb = NULL;
    sys_eunit_peri_sensor_cfg_t sensor_cfg;
    sys_usw_eunit_isr_data_t* p_isr_data = (sys_usw_eunit_isr_data_t*)p_data;
    ctc_chip_sensor_event_t event_info;
    ctc_chip_sensor_t sensor_info;
    uint8 gchip = 0;
    uint8 sensor_num;

    sal_memset(&event_info, 0, sizeof(ctc_chip_sensor_event_t));
    sal_memset(&sensor_info, 0, sizeof(ctc_chip_sensor_t));

    event_info.p_data = &sensor_info;
    sensor_num = (drv_get_chip_sub_type(lchip) >= DRV_CHIP_SUB_TYPE_3) ? SYS_AT_PERI_SENSOR_ID_MAX : (SYS_AT_PERI_SENSOR_ID_MAX/2);

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
    CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_SENSOR_MONITOR, &sen_mon_cb));
    if (NULL != sen_mon_cb)
    {
        /* read sensor info from ECPU */
        CTC_ERROR_RETURN(sys_at_eunit_get_cfg(lchip, SYS_EUNIT_CFG_SENSOR_MONITOR, &sensor_cfg));
        event_info.event_state = sensor_cfg.state;
        event_info.p_data->count = sensor_num;
        event_info.p_data->type = CTC_CHIP_SENSOR_TEMP;
        event_info.sensor_id = p_isr_data->irq_id - SYS_AT_SENSOR_INTR_BASE;
        sal_memcpy(event_info.p_data->value, sensor_cfg.sensor_value, sizeof(event_info.p_data->value));
        sen_mon_cb(gchip, &event_info);

    }
#endif
    return CTC_E_NONE;
}

#define __GPIO_INTERFACE__

int32
sys_at_peri_set_gpio_output(uint8 lchip, uint8 gpio_id, uint8 out_para)
{
    uint32 cmd = 0;
    uint32 value = 0;
    GpioOutData_m out_data;

    if (gpio_id >= MCHIP_CAP(SYS_CAP_GPIO_NUM))
    {
        SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "gpio_id:%d over max gpio id\n", gpio_id);
        return CTC_E_INVALID_PARAM;
    }
    SYS_PERI_GPIO_MAP_LCHIP_BY_GPIO_ID(lchip, gpio_id);
    cmd = DRV_IOR(GpioOutData_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &out_data));
    value = GetGpioOutData(V, cfgOutData_f, &out_data);
    if(out_para)
    {
        CTC_BIT_SET(value, gpio_id % SYS_PERI_GPIO_NUM_PER_CORE);
    }
    else
    {
        CTC_BIT_UNSET(value, gpio_id % SYS_PERI_GPIO_NUM_PER_CORE);
    }

    cmd = DRV_IOW(GpioOutData_t, DRV_ENTRY_FLAG);
    SetGpioOutData(V, cfgOutData_f, &out_data, value);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &out_data));

    return CTC_E_NONE;
}


int32
sys_at_peri_get_gpio_input(uint8 lchip, uint8 gpio_id, uint8* input)
{
    uint32 cmd = 0;
    uint32 value = 0;
    GpioReadData_m read_data;

    if (gpio_id >= MCHIP_CAP(SYS_CAP_GPIO_NUM))
    {
        SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "gpio_id:%d over max gpio id\n", gpio_id);
        return CTC_E_INVALID_PARAM;
    }
    SYS_PERI_GPIO_MAP_LCHIP_BY_GPIO_ID(lchip, gpio_id);
    cmd = DRV_IOR(GpioReadData_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &read_data));
    value = GetGpioReadData(V, gpioReadData_f, &read_data);

    if (CTC_IS_BIT_SET(value, gpio_id % SYS_PERI_GPIO_NUM_PER_CORE))
    {
        *input = TRUE;
    }
    else
    {
        *input = FALSE;
    }

    return CTC_E_NONE;
}

int32
sys_at_peri_set_gpio_mode(uint8 lchip, uint8 gpio_id, ctc_chip_gpio_mode_t mode)
{
    uint32 cmd = 0;
    uint32 out_en = 0;
    uint32 intr_en = 0;
    uint32 intr_level = 0;
    uint32 intr_mask = 0;
    uint32 gpio_act_id = 0;

    if (gpio_id >= MCHIP_CAP(SYS_CAP_GPIO_NUM))
    {
        SYS_PERI_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "gpio_id:%d over max gpio id\n", gpio_id);
        return CTC_E_INVALID_PARAM;
    }
    SYS_PERI_GPIO_MAP_LCHIP_BY_GPIO_ID(lchip, gpio_id);

    cmd = DRV_IOR(GpioOutEn_t, GpioOutEn_cfgOutEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &out_en));
    cmd = DRV_IOR(GpioIntrEn_t, GpioIntrEn_cfgIntrEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &intr_en));
    cmd = DRV_IOR(GpioIntrLevel_t, GpioIntrLevel_cfgIntrLevel_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &intr_level));
    cmd = DRV_IOR(GpioIntrMask_t, GpioIntrMask_cfgIntrMask_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &intr_mask));

    gpio_act_id = gpio_id % SYS_PERI_GPIO_NUM_PER_CORE;
    switch(mode)
    {
        case CTC_CHIP_INPUT_MODE:
            CTC_BIT_UNSET(out_en, gpio_act_id);
            CTC_BIT_UNSET(intr_en, gpio_act_id);
            break;
        case CTC_CHIP_OUTPUT_MODE:
            CTC_BIT_SET(out_en, gpio_act_id);
            CTC_BIT_UNSET(intr_en, gpio_act_id);
            break;
        case CTC_CHIP_EDGE_INTR_INPUT_MODE:
            CTC_BIT_UNSET(out_en, gpio_act_id);
            CTC_BIT_SET(intr_en, gpio_act_id);
            CTC_BIT_UNSET(intr_level, gpio_act_id);
            CTC_BIT_UNSET(intr_mask, gpio_act_id);
            break;
        case CTC_CHIP_LEVEL_INTR_INPUT_MODE:
            CTC_BIT_UNSET(out_en, gpio_act_id);
            CTC_BIT_SET(intr_en, gpio_act_id);
            CTC_BIT_SET(intr_level, gpio_act_id);
            CTC_BIT_UNSET(intr_mask, gpio_act_id);
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }
    cmd = DRV_IOW(GpioOutEn_t, GpioOutEn_cfgOutEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &out_en));
    cmd = DRV_IOW(GpioIntrEn_t, GpioIntrEn_cfgIntrEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &intr_en));
    cmd = DRV_IOW(GpioIntrLevel_t, GpioIntrLevel_cfgIntrLevel_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &intr_level));
    cmd = DRV_IOW(GpioIntrMask_t, GpioIntrMask_cfgIntrMask_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &intr_mask));

    return CTC_E_NONE;
}

#define __INIT__

STATIC int32
_sys_at_peri_led_init(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 field_value = 0;
    ds_t ds;

    /*
       1. cfg default LED clock @25MHz & reset LED module
    */
    CTC_ERROR_RETURN(sys_at_peri_set_mac_led_clock(lchip, 25000));

    field_value = 0;
    cmd = DRV_IOW(CtcBufStoreProcTopCtlReset_t, CtcBufStoreProcTopCtlReset_resetCoreLed_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

    /* 2. reset CPU MAC */
    cmd = DRV_IOR(CtcMiscCtlReset_t,DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip,0, cmd, &ds));
    SetCtcMiscCtlReset(V, resetCoreCpuMac_f , &ds, field_value);
    cmd = DRV_IOW(CtcMiscCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds))

    /* 3. cfg defualt blink interval */
    /* For Arctic units is ms */
    field_value = 0x141DD760;
    cmd = DRV_IOW(LedBlinkCfg_t, LedBlinkCfg_blinkOffInterval_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));
    cmd = DRV_IOW(LedBlinkCfg_t, LedBlinkCfg_blinkOnInterval_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

    return CTC_E_NONE;
}

STATIC int32
_sys_at_peri_i2c_init(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 field_value = 0;

    /*
    i2c master clock divider from clockSup 950M
    */

    field_value = MCHIP_CAP(SYS_CAP_I2C_REF_CLOCK) * 1000 / 25;
    cmd = DRV_IOW(I2CMasterCfg0_t, I2CMasterCfg0_clkDiv_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

    cmd = DRV_IOW(I2CMasterCfg1_t, I2CMasterCfg0_clkDiv_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

    field_value = 1;
    cmd = DRV_IOW(I2CMasterInit0_t, I2CMasterInit0_init_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

    field_value = 1;
    cmd = DRV_IOW(I2CMasterInit1_t, I2CMasterInit1_init_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

    return CTC_E_NONE;
}

int32
sys_at_peri_mdio_init(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 field_value = 0;
    ctc_chip_phy_scan_ctrl_t scan_ctl;
    MdioChanMap_m mdio_map;
    MdioCfg0_m mdio_cfg;
    MdioMiscCtl_m mdio_misc;
    uint32 chan_id = 0;
    uint16 index = 0;
    uint8 lchip_tmp = 0;
    uint8 index_tmp = 0;

    uint32 phy_port_array[MAX_PORT_NUM_PER_CHIP/32] = {0};

    sal_memset(&scan_ctl , 0, sizeof(ctc_chip_phy_scan_ctrl_t));

    for (index = 0; index < MCHIP_CAP(SYS_CAP_DP_MAX_NUM); index++)
    {
        cmd = DRV_IOW(MdioCfg0_t, DRV_ENTRY_FLAG);
        SetMdioCfg0(V, mdioCmdDoneIntervalLane0_f, &mdio_cfg, 0x0a);
        SetMdioCfg0(V, mdioInDlyLane0_f, &mdio_cfg, 0x09);
        SetMdioCfg0(V, mdioIsXgModeLane0_f, &mdio_cfg, 0);
        SetMdioCfg0(V, mdioMacPreLane0_f, &mdio_cfg, 0x1f);
        DRV_IOCTL(lchip, index, cmd, &mdio_cfg);
        cmd = DRV_IOW(MdioCfg1_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, index, cmd, &mdio_cfg);
    }

    /*
        1. cfg default MDC clock @2.5 MHz & reset MDIO module
    */
    /* cfg default MDC frequency, 2.5 MHz for 1G PHY */
    CTC_ERROR_RETURN(sys_at_peri_set_mdio_clock(lchip, CTC_CHIP_MDIO_GE, 2500));

    /* reset MDIO module */
    field_value = 0;
    cmd = DRV_IOW(CtcBufStoreProcTopCtlReset_t, CtcBufStoreProcTopCtlReset_resetCoreMdio0_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

    field_value = 1;
    cmd = DRV_IOW((MdioInit_t), MdioInit_init_f);
    DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value);

    field_value = 1;
    cmd = DRV_IOW((MdioInit_t), MdioInit_init_f);
    DRV_FIELD_IOCTL(lchip, 1, cmd, &field_value);

    cmd = DRV_IOR(MdioMiscCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &mdio_misc);
    sal_memset(phy_port_array, 0xff, sizeof(phy_port_array));
    SetMdioMiscCtl(A, linkDownDlbDetc_f, &mdio_misc, phy_port_array);
    SetMdioMiscCtl(A, linkDownIgnorMask_f, &mdio_misc, phy_port_array);
    SetMdioMiscCtl(A, linkDownIpeFwdDetc_f, &mdio_misc, phy_port_array);
    SetMdioMiscCtl(A, linkDownMetDetc_f, &mdio_misc, phy_port_array);
    SetMdioMiscCtl(A, linkDownQMgrDetc_f, &mdio_misc, phy_port_array);
    SetMdioMiscCtl(A, linkDownLinkAggDetc_f, &mdio_misc, phy_port_array);
    cmd = DRV_IOW(MdioMiscCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &mdio_misc);
    DRV_IOCTL(lchip, 1, cmd, &mdio_misc);

    /*
        MdioLinkDownDetecEn0_linkDownDetcEn_f
    */
    /* cmd = DRV_IOW(MdioLinkDownDetecEn0_t, MdioLinkDownDetecEn0_linkDownDetcEn_f);*/
    /* CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, detect_en));*/
    /* cmd = DRV_IOW(MdioLinkDownDetecEn1_t, MdioLinkDownDetecEn1_linkDownDetcEn_f);*/
    /* CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, detect_en));*/

    /*
        Init mdio scan. For no phy on demo board, just set interval
    */
    for (index = 0; index < MCHIP_CAP(SYS_CAP_MDIO_CTL_NUM); index++)
    {
        scan_ctl.op_flag = CTC_CHIP_INTERVAL_OP;
        scan_ctl.scan_interval = 100;
        scan_ctl.mdio_ctlr_id = index;
        CTC_ERROR_RETURN(sys_tsingma_peri_set_phy_scan_para(lchip, &scan_ctl));
    }
    CTC_ERROR_RETURN(sys_tsingma_peri_set_phy_scan_cfg(lchip));
    /*Config mdio channel map */
    sal_memset(&mdio_map, 0, sizeof(MdioChanMap_m));
    if (SYS_VCHIP_DUAL_CORE_MODE(lchip))
    {
        lchip_tmp = SYS_PP_BASE(lchip) + PP_NUM_PER_CORE;
        /* core 1 pp0 pp1*/
        for (index = 0; index < (SYS_AT_PERI_NUM_PER_TWO_PP-2); index++)
        {
            CTC_ERROR_RETURN(sys_usw_port_api_get_chan_by_info(lchip_tmp, 1, index/SYS_AT_PERI_MAC_NUM_PER_PP, ((index%SYS_AT_PERI_MAC_NUM_PER_PP)/SYS_AT_PERI_MAC_NUM_PER_DP), index%SYS_AT_PERI_MAC_NUM_PER_DP, (uint16 *)&chan_id));
            SetMdioChanMap(V, ppDestPort_f, &mdio_map, chan_id);
            cmd = DRV_IOW((MdioChanMap_t), DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip_tmp, index, DRV_CMD_PP_EN(cmd), &mdio_map);
        }
        /* cfg cpumac */
        for (index = (SYS_AT_PERI_NUM_PER_TWO_PP-2); index < SYS_AT_PERI_NUM_PER_TWO_PP; index++)
        {
            CTC_ERROR_RETURN(sys_usw_port_api_get_chan_by_info(lchip_tmp, 1, index % (SYS_AT_PERI_NUM_PER_TWO_PP-2), 1, SYS_AT_PERI_MAC_NUM_PER_DP, (uint16 *)&chan_id));
            SetMdioChanMap(V, ppDestPort_f, &mdio_map, chan_id);
            cmd = DRV_IOW((MdioChanMap_t), DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip_tmp, index, DRV_CMD_PP_EN(cmd), &mdio_map);
        }
        /* core 1 pp2 pp3*/
        for (index = SYS_AT_PERI_NUM_PER_TWO_PP; index < (SYS_AT_PERI_NUM_PER_TWO_PP*2 -2); index++)
        {
            index_tmp = index - SYS_AT_PERI_NUM_PER_TWO_PP;
            CTC_ERROR_RETURN(sys_usw_port_api_get_chan_by_info(lchip_tmp, 1, (index_tmp/SYS_AT_PERI_MAC_NUM_PER_PP+2), ((index_tmp%SYS_AT_PERI_MAC_NUM_PER_PP)/SYS_AT_PERI_MAC_NUM_PER_DP), index_tmp%SYS_AT_PERI_MAC_NUM_PER_DP, (uint16 *)&chan_id));
            SetMdioChanMap(V, ppDestPort_f, &mdio_map, chan_id);
            cmd = DRV_IOW((MdioChanMap_t), DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip_tmp, index, DRV_CMD_PP_EN(cmd), &mdio_map);
        }
    }
    /* core 0 pp0 pp1*/
    for (index = 0; index < (SYS_AT_PERI_NUM_PER_TWO_PP-2); index++)
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_chan_by_info(lchip, 0, index/SYS_AT_PERI_MAC_NUM_PER_PP, ((index%SYS_AT_PERI_MAC_NUM_PER_PP)/SYS_AT_PERI_MAC_NUM_PER_DP), index%SYS_AT_PERI_MAC_NUM_PER_DP, (uint16 *)&chan_id));
        SetMdioChanMap(V, ppDestPort_f, &mdio_map, chan_id);
        cmd = DRV_IOW((MdioChanMap_t), DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &mdio_map);
    }
    /* cfg cpumac */
    for (index = (SYS_AT_PERI_NUM_PER_TWO_PP-2); index < SYS_AT_PERI_NUM_PER_TWO_PP; index++)
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_chan_by_info(lchip, 0, index % (SYS_AT_PERI_NUM_PER_TWO_PP-2), 1, SYS_AT_PERI_MAC_NUM_PER_DP, (uint16 *)&chan_id));
        SetMdioChanMap(V, ppDestPort_f, &mdio_map, chan_id);
        cmd = DRV_IOW((MdioChanMap_t), DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &mdio_map);
    }
    /* core 0 pp2 pp3*/
    for (index = SYS_AT_PERI_NUM_PER_TWO_PP; index < (SYS_AT_PERI_NUM_PER_TWO_PP*2 -2); index++)
    {
        index_tmp = index - SYS_AT_PERI_NUM_PER_TWO_PP;
        CTC_ERROR_RETURN(sys_usw_port_api_get_chan_by_info(lchip, 0, (index_tmp/SYS_AT_PERI_MAC_NUM_PER_PP+2), ((index_tmp%SYS_AT_PERI_MAC_NUM_PER_PP)/SYS_AT_PERI_MAC_NUM_PER_DP), index_tmp%SYS_AT_PERI_MAC_NUM_PER_DP, (uint16 *)&chan_id));
        SetMdioChanMap(V, ppDestPort_f, &mdio_map, chan_id);
        cmd = DRV_IOW((MdioChanMap_t), DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &mdio_map);    
    }

    sys_usw_peri_set_phy_scan_en(lchip, TRUE);

    return CTC_E_NONE;
}

int32
sys_at_peri_init(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 field_value = 0;
    uint8  sensor_id = 0;
    TvsenCfg_m  sen_cfg;
    /*
        1. RlmBsr RLM level reset
    */
    field_value = 0;
    cmd = DRV_IOW(SupResetCtl_t, SupResetCtl_cfgResetCtcBufStoreProcTop_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_value));

    /* 2. cfg MAC LED default clock, reset LED Module */
    CTC_ERROR_RETURN(_sys_at_peri_led_init(lchip));

    /* 3. cfg i2c default clock, reset i2c Module */
    CTC_ERROR_RETURN(_sys_at_peri_i2c_init(lchip));

    /* 4. cfg sensor clk div and osr */
    for (sensor_id = 0; sensor_id < 5; sensor_id++)
    {
        cmd = DRV_IOR(TvsenCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, sensor_id, cmd, &sen_cfg));
        SetTvsenCfg(V, cfgTsenAdcClkDiv_f, &sen_cfg, 8);
        SetTvsenCfg(V, cfgTsenAdcOsr_f, &sen_cfg, 3);
        cmd = DRV_IOW(TvsenCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, sensor_id, cmd, &sen_cfg));
    }
    cmd = DRV_IOR(TvsenCfgTop_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &sen_cfg));
    SetTvsenCfgTop(V, cfgTsenAdcClkDiv_f, &sen_cfg, 8);
    SetTvsenCfgTop(V, cfgTsenAdcOsr_f, &sen_cfg, 3);
    cmd = DRV_IOW(TvsenCfgTop_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &sen_cfg));

#if defined E_UNIT && (FEATURE_MODE == 0)
    sys_usw_eunit_regitser_isr(lchip, SYS_EUNIT_ISR_SENSOR_MONITOR, sys_at_peri_sensor_monitor_isr);
#endif 

    return CTC_E_NONE;
}

